package com.game.miniprogram;

import com.alibaba.fastjson.JSONObject;
import com.opencsv.CSVReader;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.game.utils.PinYinUtils;
import com.game.entity.Address;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * 随机生成姓名、邮箱、身份证、地址等信息
 */
public class RandomGenerationInfo {

    private static final String provinceCsvPath = "Adress/province.csv";
    private static final String cityCsvPath = "Adress/city.csv";
    private static final String countryCsvPath = "Adress/country.csv";
    private static final String firstNamePath = "Adress/firstName.txt";
    private static final String lastNamePath = "Adress/lastName.txt";
    private static final Random random = new Random();


    // 邮箱域名列表
    private static final List<String> EMAIL_DOMAINS = Arrays.asList(
            "@qq.com", "@163.com", "@gmail.com", "@outlook.com"
    );

    public static void main(String[] args) {
        String outPath = "D:\\随机信息生成" + System.currentTimeMillis() + ".xlsx";
        generateExcel(100000, outPath);
    }

    public static void generateExcel(int count, String filePath) {
        try {
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("个人信息");

            // 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {
                    "拼音姓", "拼音名", "拼音姓名", "中文姓", "中文名", "中文姓名", "性别",
                    "邮箱", "出生日期", "身份证号", "手机号", "详细地址", "拼音地址"
            };

            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }
            List<Address> provinceList = getProvince();
            List<Address> cityList = getCity(cityCsvPath);
            List<Address> countryList = getCity(countryCsvPath);
            List<String> lastNameList = getName(lastNamePath);
            List<String> firstNameList = getName(firstNamePath);
            // 生成数据行
            Random random = new Random();
            for (int i = 0; i < count; i++) {
                Row row = sheet.createRow(i + 1);

                // 随机生成性别
                boolean isMale = random.nextBoolean();

                // 随机选择姓
                String lastName = generateLastName(lastNameList);
                String pyLastName = PinYinUtils.getPinYin(lastName).toUpperCase();

                // 随机选择名
                String firstName = generateFirstName(firstNameList);
                String pyFirstName = PinYinUtils.getPinYin(firstName).toUpperCase();

                // 姓名
                String nameCN = lastName + firstName;

                // 拼音姓名
                String pyName = pyLastName + " " + pyFirstName;

                // 生成邮箱
                String email = generateEmail();

                // 生成手机号
                String phoneNumber = generatePhoneNumber();

                // 生成出生日期
                LocalDate birthDate = generateRandomBirthDate();

                // 生成地址
                Map<String, String> addressMap = generateAddress(provinceList,cityList,countryList);
                String province = addressMap.get("province");
                String city = addressMap.get("city");
                String country = addressMap.get("country");
                String address = province+city+country;
                String pinyinAddress = PinYinUtils.coverCNToPY(address).toUpperCase();

                // 身份证号
                String idCard = generateIdCard(birthDate, isMale, addressMap);

                // 填充数据到行
                row.createCell(0).setCellValue(pyLastName);
                row.createCell(1).setCellValue(pyFirstName);
                row.createCell(2).setCellValue(pyName);
                row.createCell(3).setCellValue(lastName);
                row.createCell(4).setCellValue(firstName);
                row.createCell(5).setCellValue(nameCN);
                row.createCell(6).setCellValue(isMale ? "male" : "female");
                row.createCell(7).setCellValue(email);
                row.createCell(8).setCellValue(birthDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                row.createCell(9).setCellValue(idCard);
                row.createCell(10).setCellValue(phoneNumber);
                row.createCell(11).setCellValue(address);
                row.createCell(12).setCellValue(pinyinAddress);
            }

            // 自动调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }

            // 写入文件
            try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
                workbook.write(fileOut);
            } finally {
                workbook.close();
                System.out.println("文件已生成");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String generateEmail() {
        String domain = EMAIL_DOMAINS.get(random.nextInt(EMAIL_DOMAINS.size()));
        StringBuilder sb = new StringBuilder();
        if ("qq.com".equals(domain)) {
            int length = random.nextInt(7) + 5;
            sb.append(random.nextInt(9) + 1);
            for (int i = 1; i < length; i++) {
                sb.append(random.nextInt(10));
            }
        } else {
            int length = random.nextInt(8) + 3;
            // 确保用户名以字母开头
            char firstChar = (char) ('a' + random.nextInt(26));
            sb.append(firstChar);

            // 生成剩余的字符
            for (int i = 1; i < length; i++) {
                // 50%概率生成字母，50%概率生成数字
                if (random.nextBoolean()) {
                    char c = (char) ('a' + random.nextInt(26));
                    sb.append(c);
                } else {
                    char c = (char) ('0' + random.nextInt(10));
                    sb.append(c);
                }
            }
        }
        return sb + domain;
    }

    private static String generateFirstName(List<String> firstNameList) {
        boolean isSingleName = random.nextBoolean();
        String name = "";
        if (isSingleName) {
            name = firstNameList.get(random.nextInt(firstNameList.size()));
        } else {
            String name1 = firstNameList.get(random.nextInt(firstNameList.size()));
            String name2 = firstNameList.get(random.nextInt(firstNameList.size()));
            name = name1 + name2;
        }
        return name;
    }

    private static String generateLastName(List<String> lastNameList) {
        int i = random.nextInt(lastNameList.size());
        return lastNameList.get(i);
    }

    private static List<String> getName(String csvPath) {
        List<String> list = new ArrayList<>();
        try (InputStream inputStream = RandomGenerationInfo.class.getClassLoader().getResourceAsStream(csvPath);
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {

            String line;
            // 逐行读取文件并添加到列表
            while ((line = reader.readLine()) != null) {
                list.addAll(Arrays.asList(line.split(",")));
            }
        } catch (IOException e) {
            System.err.println("读取资源文件时发生错误: " + e.getMessage());
        }
        return list;
    }

    private static List<Address> getProvince() {
        List<Address> addressList = new ArrayList<>();
        CSVReader reader = null;
        try {
            InputStream in = RandomGenerationInfo.class.getClassLoader().getResourceAsStream(provinceCsvPath);
            reader = new CSVReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            String[] data;
            int count = 1;
            while ((data = reader.readNext()) != null) {
                if (count > 1) {
                    Address province = new Address();
                    province.setId(data[0]);
                    province.setCityName(data[1]);
                    province.setIdNoNumber(data[2]);
                    province.setCityType(data[3]);
                    addressList.add(province);
                }
                count++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return addressList;
    }

    private static List<Address> getCity(String csvPath) {
        List<Address> addressList = new ArrayList<>();
        CSVReader reader = null;
        try {
            InputStream in = RandomGenerationInfo.class.getClassLoader().getResourceAsStream(csvPath);
            reader = new CSVReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            String[] data;
            int count = 1;
            while ((data = reader.readNext()) != null) {
                if (count > 1) {
                    Address province = new Address();
                    if (data[0] == null || data[1] == null || data[2] == null || data[3] == null) {
                        continue;
                    }
                    province.setId(data[0]);
                    province.setSuperId(data[1]);
                    province.setCityName(data[2]);
                    province.setIdNoNumber(data[3]);
                    addressList.add(province);
                }
                count++;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return addressList;
    }

    // 生成随机出生日期（18-70岁之间）
    private static LocalDate generateRandomBirthDate() {
        long minDay = LocalDate.of(1955, 1, 1).toEpochDay();
        long maxDay = LocalDate.of(2007, 12, 31).toEpochDay();
        long randomDay = ThreadLocalRandom.current().nextLong(minDay, maxDay);
        return LocalDate.ofEpochDay(randomDay);
    }

    // 生成身份证号
    private static String generateIdCard(LocalDate birthDate, boolean isMale, Map<String, String> map) {
        String idNo = map.get("idNo");
        String cityType = map.get("cityType");
        String province = map.get("province");
        // 香港和澳门的证件号特殊处理
        if ("2".equals(cityType)) {
            if (province.contains("香港")) {
                StringBuilder result = new StringBuilder();
                // 随机决定字母部分长度（1或2）
                int letterLength = random.nextInt(2) + 1;
                // 生成字母部分
                for (int i = 0; i < letterLength; i++) {
                    char c = (char) (random.nextInt(26) + 'A');
                    result.append(c);
                }

                // 随机决定数字部分长度（6或7）
                int digitLength = 8 - letterLength;
                // 生成数字部分
                for (int i = 0; i < digitLength; i++) {
                    result.append(random.nextInt(10));
                }
                return result.toString();
            }
            if (province.contains("澳门")) {
                String[] id1 = {"P", "R"};
                return id1[random.nextInt(id1.length)] + (random.nextInt(9000000) + 1000000);
            }
        } else {
            String birthDateStr = birthDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            // 生成顺序码（3位数字）
            int sequenceCode = ThreadLocalRandom.current().nextInt(1, 999);
            String sequenceCodeStr = String.format("%03d", sequenceCode);
            int lastDigit = sequenceCode % 10;
            if ((isMale && lastDigit % 2 == 0) || (!isMale && lastDigit % 2 != 0)) {
                // 调整最后一位数字
                sequenceCode += (isMale ? 1 : -1);
                sequenceCodeStr = String.format("%03d", sequenceCode);
            }
            // 拼接前17位
            String first17Digits = idNo + birthDateStr + sequenceCodeStr;
            // 计算校验码
            char checkCode = calculateCheckCode(first17Digits);
            return first17Digits + checkCode;
        }
        return "";
    }

    private static char calculateCheckCode(String idCard17) {
        // 身份证校验码权重因子
        int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        // 校验码对应表
        char[] checkCodeList = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

        int sum = 0;
        for (int i = 0; i < idCard17.length(); i++) {
            sum += Character.getNumericValue(idCard17.charAt(i)) * weights[i];
        }

        int mod = sum % 11;
        return checkCodeList[mod];
    }

    // 生成手机号
    private static String generatePhoneNumber() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder("1");

        // 第二位数字（3-9）
        sb.append(random.nextInt(7) + 3);

        // 后面9位数字
        for (int i = 0; i < 9; i++) {
            sb.append(random.nextInt(10));
        }

        return sb.toString();
    }

    // 生成地址
    private static Map<String, String> generateAddress(List<Address> provinceList,List<Address> cityList,List<Address> countryList) {
        Map<String, String> map = new HashMap<>();
        String idNo = "";
        // 省
        Address provinceAddress = provinceList.get(random.nextInt(provinceList.size()));
        String cityType = provinceAddress.getCityType();
        String provinceId = provinceAddress.getId();
        if (!"2".equals(cityType)) {
            idNo += provinceAddress.getIdNoNumber();
        }
        map.put("province",provinceAddress.getCityName());

        // 市
        Map<String, List<Address>> cityMap = cityList.stream().filter(Address -> Address.getSuperId() != null).collect(Collectors.groupingBy(Address::getSuperId));
        List<Address> cityAddresseList = cityMap.get(provinceId);
        Address cityAddress = cityAddresseList.get(random.nextInt(cityAddresseList.size()));
        String cityId = cityAddress.getSuperId();
        if (!"2".equals(cityType)) {
            idNo += cityAddress.getIdNoNumber();
        }
        map.put("city",cityAddress.getCityName());

        // 县
        Map<String, List<Address>> countryMap = countryList.stream().filter(Address -> Address.getSuperId() != null).collect(Collectors.groupingBy(Address::getSuperId));
        List<Address> countryAddresselist = countryMap.get(cityId);
        Address countryAddress = countryAddresselist.get(random.nextInt(countryAddresselist.size()));
        if (!"2".equals(cityType)) {
            idNo += countryAddress.getIdNoNumber();
        }
        map.put("country",countryAddress.getCityName());

        map.put("cityType", cityType);
        map.put("idNo", idNo);
        return map;
    }
}
